package org.graduation.IM.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import org.graduation.IM.service.FriendsService;
import org.graduation.feignapi.UserClient;
import org.graduation.model.common.IM.Friends;
import org.graduation.model.common.ResponseResult;
import org.graduation.model.common.user.User;
import org.graduation.utils.Token;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.List;

@RestController
@RequestMapping("/IM/friends")
public class FriendsController {
    @Autowired
    private FriendsService friendsService;
    @Autowired
    private Token tokenTool;
    @Autowired
    private UserClient userClient;
    @Autowired
    private RedisTemplate redisTemplate;

    private String redisKey = "friends:";

    @PostMapping("/add/uid/{uid}")
    public ResponseResult addFriends(@RequestHeader("Authorization") String token, @PathVariable("uid") Integer uid) {
        Integer userUid = tokenTool.getUidByToken(token);
        LambdaQueryWrapper<Friends> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper
                .eq(Friends::getUidA, userUid)
                .eq(Friends::getUidB, uid)
                .lt(Friends::getStatus, 2);
        Friends friends = friendsService.getOne(queryWrapper);
        if (friends != null) {
            return ResponseResult.failed("已经添加过该好友");
        } else {
            friends = new Friends(userUid, uid, 0);
            friendsService.save(friends);
            redisTemplate.delete(getRedisKey(userUid));
            return ResponseResult.success();
        }
    }

    @PostMapping("/add/email/{email}")
    public ResponseResult addFriendsByEmail(@RequestHeader("Authorization") String tokenStr, @PathVariable("email") String email) {
        Integer me = tokenTool.getUidByToken(tokenStr);
        User friendsUserInfo = userClient.info(email).getData();
        if(friendsUserInfo == null){
            return ResponseResult.failed("用户不存在");
        }
        return addFriends(tokenStr, friendsUserInfo.getUid());
    }

    @PostMapping("/agree/{uid}")
    public ResponseResult agreeFriends(@RequestHeader("Authorization") String token, @PathVariable("uid") Integer uid) {
        Integer uidB = tokenTool.getUidByToken(token);
        LambdaUpdateWrapper<Friends> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper
                .eq(Friends::getUidA, uid)
                .eq(Friends::getUidB, uidB)
                .eq(Friends::getStatus, 0)
                .set(Friends::getStatus, 1);
        return friendsService.update(updateWrapper) ? ResponseResult.success() : ResponseResult.failed();
    }

    @PostMapping("/rejection/{uid}")
    public ResponseResult rejectionFriends(@RequestHeader("Authorization") String token, @PathVariable("uid") Integer uid) {
        Integer uidB = tokenTool.getUidByToken(token);
        LambdaUpdateWrapper<Friends> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper
                .eq(Friends::getUidA, uid)
                .eq(Friends::getUidB, uidB)
                .eq(Friends::getStatus, 0)
                .set(Friends::getStatus, 2);
        return friendsService.update(updateWrapper) ? ResponseResult.success() : ResponseResult.failed();
    }

    @PostMapping("/delete/{uid}")
    public ResponseResult deleteFriends(@RequestHeader("Authorization") String token, @PathVariable("uid") Integer uid) {
        Integer my = tokenTool.getUidByToken(token);
        LambdaQueryWrapper<Friends> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper
                .eq(Friends::getUidA, my)
                .eq(Friends::getUidB, uid)
                .eq(Friends::getStatus, 1)
                .or()
                .eq(Friends::getUidB, my)
                .eq(Friends::getUidA, uid)
                .eq(Friends::getStatus, 1);
        ;
        return friendsService.remove(queryWrapper) ? ResponseResult.success() : ResponseResult.failed();
    }

    @GetMapping("/list")
    public ResponseResult<List<User>> getFriends(@RequestHeader("Authorization") String token) {
        Integer uid = tokenTool.getUidByToken(token);
        List<User> friendsUserList = redisTemplate.opsForList().range(getRedisKey(uid), 0, -1);
        if (friendsUserList != null && !friendsUserList.isEmpty()) {
            return ResponseResult.success(friendsUserList);
        }
        LambdaQueryWrapper<Friends> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Friends::getStatus, 1);
        queryWrapper.and(wrapper -> wrapper
                .eq(Friends::getUidA, uid)
                .or()
                .eq(Friends::getUidB, uid)
        );
        List<Friends> friendsList = friendsService.list(queryWrapper);
        if (friendsList.isEmpty()) {
            return ResponseResult.success();
        }
        List<Integer> friendsUid = new ArrayList<>();
        for (Friends friends : friendsList) {
            if (friends.getUidA().equals(uid)) {
                friendsUid.add(friends.getUidB());
            } else {
                friendsUid.add(friends.getUidA());
            }
        }
        ResponseResult<List<User>> feignResponse = userClient.search(friendsUid);
        for (User user : feignResponse.getData()) {
            redisTemplate.opsForList().rightPush(getRedisKey(uid), user);
        }
        redisTemplate.expire(getRedisKey(uid), 60 * 60 * 24, java.util.concurrent.TimeUnit.SECONDS);
        return feignResponse;
    }

    @GetMapping("/list/ops")
    public ResponseResult<List<User>> ops(@RequestHeader("Authorization") String token) {
        Integer my = tokenTool.getUidByToken(token);
        LambdaQueryWrapper<Friends> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper
                .eq(Friends::getUidB, my)
                .eq(Friends::getStatus, 0);
        List<Friends> opsFriendsList = friendsService.list(queryWrapper);
        List<Integer> opsFriendsUidList = new ArrayList<>();
        for (Friends friends : opsFriendsList) {
            opsFriendsUidList.add(friends.getUidA());
        }
        if(opsFriendsUidList.isEmpty()){
            return ResponseResult.success();
        }
        ResponseResult<List<User>> feignResponse = userClient.search(opsFriendsUidList);
        return feignResponse;
    }

    private String getRedisKey(Integer uid) {
        return redisKey + uid;
    }
}
